/* Classic Ladder Project */
/* Copyright (C) 2001-2011 Marc Le Douarain */
/* http://membres.lycos.fr/mavati/classicladder/ */
/* http://www.sourceforge.net/projects/classicladder */
/* February 2011 */
/* ------------------------------------------------------ */
/* Monitor protocol - All the requests...                 */
/* ------------------------------------------------------ */
/* This library is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU Lesser General Public */
/* License as published by the Free Software Foundation; either */
/* version 2.1 of the License, or (at your option) any later version. */

/* This library is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU */
/* Lesser General Public License for more details. */

/* You should have received a copy of the GNU Lesser General Public */
/* License along with this library; if not, write to the Free Software */
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>

#include "classicladder.h"
#include "global.h"
#include "vars_access.h"
#include "monitor_protocol.h"
#include "monitor_transfer.h"
#include "tasks.h"
#include "files.h"
#ifdef GTK_INTERFACE
#include <gtk/gtk.h>
#include "menu_and_toolbar_gtk.h"
#else
#include <sys/types.h>
#include <signal.h>
#endif

// look at interesting MONITOR_TEST_ONLY_NO_RESPONSES_USE in classicladder.h to debug frames
// with just one executable connecting to itself...

char * MonitorParseGeneralResponseToSwitch( char * TextReq, char SlaveMode )
{
	char * TextReqWithValues = NULL;
	cJSON *JsonRoot;
	JsonRoot = cJSON_Parse(TextReq);
	if ( JsonRoot )
	{
		cJSON * CommandReqObj = cJSON_GetObjectItem( JsonRoot,"ReqCL" );
		if ( CommandReqObj )
		{
			char * CommandReq = CommandReqObj->valuestring;
			if ( strcmp( CommandReq, "ReadVars" )==0 )
				MonitorParseResponseReadVars( JsonRoot, SlaveMode );
			else if ( strcmp( CommandReq, "ReadRung" )==0 )
				MonitorParseResponseReadRung( JsonRoot, SlaveMode );
			else if ( strcmp( CommandReq, "ReadSequential" )==0 )
				MonitorParseResponseReadSequential( JsonRoot, SlaveMode );
			else if ( strcmp( CommandReq, "SetRunStopState" )==0 )
				MonitorParseResponseSetRunStopState( JsonRoot, SlaveMode );
			else if ( strcmp( CommandReq, "ResetTarget" )==0 )
				MonitorParseResponseResetTarget( JsonRoot, SlaveMode );
			else if ( strcmp( CommandReq, "SetClockTime" )==0 )
				MonitorParseResponseSetClockTime( JsonRoot, SlaveMode );
			else if ( strcmp( CommandReq, "GetTargetInfosVersion" )==0 )
				MonitorParseResponseGetTargetInfosVersion( JsonRoot, SlaveMode );
			else if ( strcmp( CommandReq, "GetProjectInfos" )==0 )
				MonitorParseResponseGetProjectProperties( JsonRoot, SlaveMode );
			else if ( strcmp( CommandReq, "Transfer" )==0 )
				MonitorParseResponseFileTransfer( JsonRoot, SlaveMode );
			else if ( strcmp( CommandReq, "RebootTarget" )==0 )
				MonitorParseResponseRebootTarget( JsonRoot, SlaveMode );
			else
				printf("mon: ****** FAILED TO FIND REQUEST TO PARSE !!! ******\n");

			if ( SlaveMode )
			{
				TextReqWithValues = cJSON_Print( JsonRoot );
			}
		}
		else
		{
			printf( "mon: ****** FAILED TO FIND 'ReqCL' KEYWORD TAG !!! ******\n" );
		}
		cJSON_Delete( JsonRoot );
	}
	else
	{
		printf( "mon: ****** FAILED TO PARSE JSON (for %s) !!! ******\n", SlaveMode?"slave":"master" );
	}
	return TextReqWithValues;
}


// used to exchange the "free vars spy" + system time vars + functions blocks displayed on screen...
#define NBR_FREE_VARS_READ ( NBR_FREE_VAR_SPY + 3 + NBR_FUNCTIONS_BLOCKS_VARS_TO_MONITOR )
//for the master, to ask to read variables values
char * MonitorCreateRequestReadVars( void )
{
	//create request...
	cJSON *JsonRoot;
	char * TextReq;
	int ScanColumn = 0;
	int FreeVarsType[ NBR_FREE_VARS_READ ];
	int FreeVarsNum[ NBR_FREE_VARS_READ ];
	int NbrFreeVars = 0;
	int ScanVar;
	
	JsonRoot = cJSON_CreateObject();
	
	cJSON_AddStringToObject( JsonRoot, "ReqCL", "ReadVars" );
	
	cJSON_AddNumberToObject( JsonRoot, "FirstBoolVar", InfosGUI->ValOffsetBoolVar[ ScanColumn++ ] );
	cJSON_AddNumberToObject( JsonRoot, "NbrBoolVars", NBR_BOOLS_VAR_SPY );
	cJSON_AddNumberToObject( JsonRoot, "FirstInputVar", InfosGUI->ValOffsetBoolVar[ ScanColumn++ ] );
	cJSON_AddNumberToObject( JsonRoot, "NbrInputVars", NBR_BOOLS_VAR_SPY );
	cJSON_AddNumberToObject( JsonRoot, "FirstOutputVar", InfosGUI->ValOffsetBoolVar[ ScanColumn++ ] );
	cJSON_AddNumberToObject( JsonRoot, "NbrOutputVars", NBR_BOOLS_VAR_SPY );

	// to read the "free vars spy" values
	for( ScanVar=0; ScanVar<NBR_FREE_VAR_SPY; ScanVar++ )
	{
		FreeVarsType[ NbrFreeVars ] = InfosGUI->FreeVarSpy[ ScanVar ].VarType;
		FreeVarsNum[ NbrFreeVars ] = InfosGUI->FreeVarSpy[ ScanVar ].VarNum;
		NbrFreeVars++;
	}
	// to read 3 system time variables
	for( ScanVar=0; ScanVar<3; ScanVar++ )
	{
		FreeVarsType[ NbrFreeVars ] = VAR_WORD_SYSTEM;
		FreeVarsNum[ NbrFreeVars ] = ScanVar;
		NbrFreeVars++;
	}
	// to read functions blocks displayed on screen...
	for( ScanVar=0; ScanVar<InfosGUI->NbrFunctionsBlocksVarsToMonitor; ScanVar++ )
	{
		if ( NbrFreeVars<NBR_FREE_VARS_READ )
		{
			FreeVarsType[ NbrFreeVars ] = InfosGUI->FunctionsBlocksVarsToMonitor[ ScanVar ].VarType;
			FreeVarsNum[ NbrFreeVars ] = InfosGUI->FunctionsBlocksVarsToMonitor[ ScanVar ].VarNum;
			NbrFreeVars++;
		}
	}

	cJSON_AddItemToObject( JsonRoot, "VarsTypes", cJSON_CreateIntArray( FreeVarsType, NbrFreeVars ) );
	cJSON_AddItemToObject( JsonRoot, "VarsNums", cJSON_CreateIntArray( FreeVarsNum, NbrFreeVars ) );
	
	// Print to text, Delete the cJSON, use it, release the string.
	TextReq = cJSON_Print( JsonRoot );
	cJSON_Delete( JsonRoot );
//to reuse it after now...	free( TextReq );
	return TextReq;
}

void MonitorParseResponseReadVars( cJSON *JsonRoot, char SlaveMode )
{
	char Buff[ 50 ];
	int ScanVar;
	int ColumnVar;
	int VarBoolType[ NBR_TYPE_BOOLS_SPY ] = { VAR_MEM_BIT, VAR_PHYS_INPUT, VAR_PHYS_OUTPUT };
	char * pTagNameBoolValues[ NBR_TYPE_BOOLS_SPY ] = { "BoolVarsValues", "InputVarsValues", "OutputVarsValues" };
	int FirstBoolVar[ NBR_TYPE_BOOLS_SPY ];
	int NbrBoolVar[ NBR_TYPE_BOOLS_SPY ];
	int NbrFreeVars = cJSON_GetArraySize( cJSON_GetObjectItem( JsonRoot,"VarsTypes" ) );
	FirstBoolVar[ 0 ] = cJSON_GetObjectItem( JsonRoot,"FirstBoolVar" )->valueint;
	FirstBoolVar[ 1 ] = cJSON_GetObjectItem( JsonRoot,"FirstInputVar" )->valueint;
	FirstBoolVar[ 2 ] = cJSON_GetObjectItem( JsonRoot,"FirstOutputVar" )->valueint;
	NbrBoolVar[ 0 ] = cJSON_GetObjectItem( JsonRoot,"NbrBoolVars" )->valueint;
	NbrBoolVar[ 1 ] = cJSON_GetObjectItem( JsonRoot,"NbrInputVars" )->valueint;
	NbrBoolVar[ 2 ] = cJSON_GetObjectItem( JsonRoot,"NbrOutputVars" )->valueint;
	
	if ( !SlaveMode )
	{
		// get values from the response of the slave...
		// --------------------------------------------
		int TargetState;
		cJSON * JsonLastDuration;
		
		for( ColumnVar=0; ColumnVar<NBR_TYPE_BOOLS_SPY; ColumnVar++ )
		{
			char * BoolValues = cJSON_GetObjectItem( JsonRoot, pTagNameBoolValues[ ColumnVar ] )->valuestring;
#ifndef MONITOR_TEST_ONLY_NO_RESPONSES_USE
			for( ScanVar=0; ScanVar<NbrBoolVar[ ColumnVar ]; ScanVar++ )
			{
				int BoolVal = (BoolValues[ ScanVar ]=='1')?1:0;
//printf("write bool var %d/%d with %d\n", VarBoolType[ColumnVar],FirstBoolVar[ ColumnVar ]+ScanVar,BoolVal);
				WriteVar( VarBoolType[ColumnVar], FirstBoolVar[ ColumnVar ]+ScanVar, BoolVal );
			}
#endif
		}
		
		for( ScanVar=0; ScanVar<NbrFreeVars; ScanVar++ )
		{
			int VarType = cJSON_GetArrayItem( cJSON_GetObjectItem( JsonRoot,"VarsTypes" ), ScanVar )->valueint;
			int VarNum = cJSON_GetArrayItem( cJSON_GetObjectItem( JsonRoot,"VarsNums" ), ScanVar )->valueint;
			int VarValue = cJSON_GetArrayItem( cJSON_GetObjectItem( JsonRoot,"VarsValues" ), ScanVar )->valueint;
//			printf("freevar%d (%d/%d) = %d\n", ScanVar, VarType, VarNum, VarValue );
#ifndef MONITOR_TEST_ONLY_NO_RESPONSES_USE
			WriteVar( VarType, VarNum, VarValue );
#endif
		}
		
		TargetState = cJSON_GetObjectItem( JsonRoot,"State" )->valueint;
#ifdef GTK_INTERFACE
printf("TARGET STATE IS = %s (current=%s)\n", _ConvStateInString(TargetState),_ConvStateInString(InfosGUI->TargetMonitor.LatestTargetState) );
		if ( TargetState!=InfosGUI->TargetMonitor.LatestTargetState )
			SetGtkMenuStateForRunStopSwitch( TargetState==STATE_RUN );
#endif
		InfosGUI->TargetMonitor.LatestTargetState = TargetState;
		JsonLastDuration = cJSON_GetObjectItem( JsonRoot, "LastDurationLogicRT" );
		if ( JsonLastDuration )
			InfosGene->DurationOfLastScan = JsonLastDuration->valueint;
	}
	else
	{
		// adds values responses for the response to the master !
		// ------------------------------------------------------
		for( ColumnVar=0; ColumnVar<NBR_TYPE_BOOLS_SPY; ColumnVar++ )
		{
			Buff[0] = '\0';
			for( ScanVar=0; ScanVar<NbrBoolVar[ ColumnVar ]; ScanVar++ )
				strcat( Buff, ReadVar( VarBoolType[ColumnVar], FirstBoolVar[ ColumnVar ]+ScanVar )?"1":"0" );
			cJSON_AddStringToObject( JsonRoot, pTagNameBoolValues[ ColumnVar ], Buff );
		}
		
		int FreeVarsValues[ NBR_FREE_VARS_READ ];
		for( ScanVar=0; ScanVar<NbrFreeVars; ScanVar++ )
		{
			int VarType = cJSON_GetArrayItem( cJSON_GetObjectItem( JsonRoot,"VarsTypes" ), ScanVar )->valueint;
			int VarNum = cJSON_GetArrayItem( cJSON_GetObjectItem( JsonRoot,"VarsNums" ), ScanVar )->valueint;
			FreeVarsValues[ ScanVar ] = ReadVar( VarType, VarNum );
		}
		cJSON_AddItemToObject( JsonRoot, "VarsValues", cJSON_CreateIntArray( FreeVarsValues, NbrFreeVars ) );
		// current run/stop state of the target !
		cJSON_AddNumberToObject( JsonRoot, "State", InfosGene->LadderState );
#if defined( RT_SUPPORT ) || defined( __XENO__ )
		cJSON_AddNumberToObject( JsonRoot, "LastDurationLogicRT", InfosGene->DurationOfLastScan );
#endif
	}
}


//for the master, to ask to read a rung displayed
char * MonitorCreateRequestReadRung( int NumRung )
{
	//create request...
	cJSON *JsonRoot;
	char * TextReq;
	
	JsonRoot = cJSON_CreateObject();
	
	cJSON_AddStringToObject( JsonRoot, "ReqCL", "ReadRung" );
	
	cJSON_AddNumberToObject( JsonRoot, "NumRung", NumRung );
	
	// Print to text, Delete the cJSON, use it, release the string.
	TextReq = cJSON_Print( JsonRoot );
	cJSON_Delete( JsonRoot );
//to reuse it after now...	free( TextReq );
	return TextReq;
}

void MonitorParseResponseReadRung( cJSON *JsonRoot, char SlaveMode )
{
	char Buff[ 50 ];
	char BuffAttrib[ 50 ];
	int ScanX,ScanY;
	int NumRung = cJSON_GetObjectItem( JsonRoot,"NumRung" )->valueint;
	StrRung * PtrRung = &RungArray[ NumRung ];
	if ( !SlaveMode )
	{
		// get values from the response of the slave...
		// --------------------------------------------
		for (ScanY=0;ScanY<RUNG_HEIGHT;ScanY++)
		{
			char * StringValues;
			sprintf( BuffAttrib, "DynamicLine%d", ScanY );
			StringValues = cJSON_GetObjectItem( JsonRoot, BuffAttrib )->valuestring;
#ifndef MONITOR_TEST_ONLY_NO_RESPONSES_USE
			for(ScanX=0;ScanX<RUNG_WIDTH;ScanX++)
			{
				PtrRung->Element[ScanX][ScanY].DynamicState = (StringValues[ ScanX ]&1)?1:0;
				PtrRung->Element[ScanX][ScanY].DynamicInput = (StringValues[ ScanX ]&2)?1:0;
				PtrRung->Element[ScanX][ScanY].DynamicOutput = (StringValues[ ScanX ]&4)?1:0;
			}
#endif
		}
	}
	else
	{
		// adds values responses for the response to the master !
		// ------------------------------------------------------
		for (ScanY=0;ScanY<RUNG_HEIGHT;ScanY++)
		{
			char * pBuff = Buff;
			for(ScanX=0;ScanX<RUNG_WIDTH;ScanX++)
			{
				*pBuff = '0';
				if ( PtrRung->Element[ScanX][ScanY].DynamicState )
					*pBuff |= 1;
				if ( PtrRung->Element[ScanX][ScanY].DynamicInput )
					*pBuff |= 2;
				if ( PtrRung->Element[ScanX][ScanY].DynamicOutput )
					*pBuff |= 4;
				pBuff++;
			}
			*pBuff = '\0';
			sprintf( BuffAttrib, "DynamicLine%d", ScanY );
			cJSON_AddStringToObject( JsonRoot, BuffAttrib, Buff );
		}
	}
}

//for the master, to ask to read a sequential page displayed
char * MonitorCreateRequestReadSequential( int NumPage )
{
	//create request...
	cJSON *JsonRoot;
	char * TextReq;
	
	JsonRoot = cJSON_CreateObject();
	
	cJSON_AddStringToObject( JsonRoot, "ReqCL", "ReadSequential" );
	
	cJSON_AddNumberToObject( JsonRoot, "NumPage", NumPage );
	
	// Print to text, Delete the cJSON, use it, release the string.
	TextReq = cJSON_Print( JsonRoot );
	cJSON_Delete( JsonRoot );
//to reuse it after now...	free( TextReq );
	return TextReq;
}

void MonitorParseResponseReadSequential( cJSON *JsonRoot, char SlaveMode )
{
	int NbrStepsDisp = 0;
	int StepNumDisp[ NBR_STEPS ];
	int StepState[ NBR_STEPS ];
	int NbrTransisDisp = 0;
	int TransiNumDisp[ NBR_TRANSITIONS ];
	int TransiState[ NBR_TRANSITIONS ];
	int ScanStep,ScanTransi;
	StrStep * pStep;
	StrTransition * pTransi;
	int NumPageDisplayed = cJSON_GetObjectItem( JsonRoot,"NumPage" )->valueint;
	if ( !SlaveMode )
	{
		// get values from the response of the slave...
		// --------------------------------------------
		NbrStepsDisp = cJSON_GetArraySize( cJSON_GetObjectItem( JsonRoot,"StepsNums" ) );
		for( ScanStep=0; ScanStep<NbrStepsDisp; ScanStep++ )
		{
			int StepNum = cJSON_GetArrayItem( cJSON_GetObjectItem( JsonRoot,"StepsNums" ), ScanStep )->valueint;
			int StepState = cJSON_GetArrayItem( cJSON_GetObjectItem( JsonRoot,"StepsStates" ), ScanStep )->valueint;
#ifndef MONITOR_TEST_ONLY_NO_RESPONSES_USE
			Sequential->Step[ StepNum ].Activated = StepState;
#endif
		}
		NbrTransisDisp = cJSON_GetArraySize( cJSON_GetObjectItem( JsonRoot,"TransisNums" ) );
		for( ScanTransi=0; ScanTransi<NbrStepsDisp; ScanTransi++ )
		{
			int TransiNum = cJSON_GetArrayItem( cJSON_GetObjectItem( JsonRoot,"TransisNums" ), ScanTransi )->valueint;
			int TransiState = cJSON_GetArrayItem( cJSON_GetObjectItem( JsonRoot,"TransisStates" ), ScanTransi )->valueint;
#ifndef MONITOR_TEST_ONLY_NO_RESPONSES_USE
			Sequential->Transition[ TransiNum ].Activated = TransiState;
#endif
		}
	}
	else
	{
		// adds values responses for the response to the master !
		// ------------------------------------------------------
		
		// scan for steps and transitions displayed on this page
		for( ScanStep=0; ScanStep<NBR_STEPS; ScanStep++ )
		{
			pStep = &Sequential->Step[ ScanStep ];
			if ( pStep->NumPage==NumPageDisplayed )
			{
				StepNumDisp[ NbrStepsDisp ] = ScanStep;
				StepState[ NbrStepsDisp ] = pStep->Activated?1:0;
				NbrStepsDisp++;
			}
		}
		cJSON_AddItemToObject( JsonRoot, "StepsNums", cJSON_CreateIntArray( StepNumDisp, NbrStepsDisp ) );
		cJSON_AddItemToObject( JsonRoot, "StepsStates", cJSON_CreateIntArray( StepState, NbrStepsDisp ) );
		for( ScanTransi=0; ScanTransi<NBR_TRANSITIONS; ScanTransi++ )
		{
			pTransi = &Sequential->Transition[ ScanTransi ];
			if ( pTransi->NumPage==NumPageDisplayed )
			{
				TransiNumDisp[ NbrTransisDisp ] = ScanTransi;
				TransiState[ NbrTransisDisp ] = pTransi->Activated?1:0;
				NbrTransisDisp++;
			}
		}
		cJSON_AddItemToObject( JsonRoot, "TransisNums", cJSON_CreateIntArray( TransiNumDisp, NbrTransisDisp ) );
		cJSON_AddItemToObject( JsonRoot, "TransisStates", cJSON_CreateIntArray( TransiState, NbrTransisDisp ) );
	}
}

//for the master, to ask to set run/stop state
char * MonitorCreateRequestSetRunStopState( int RunStopStateWanted )
{
	//create request...
	cJSON *JsonRoot;
	char * TextReq;
	
	JsonRoot = cJSON_CreateObject();
	
	cJSON_AddStringToObject( JsonRoot, "ReqCL", "SetRunStopState" );
	
	cJSON_AddNumberToObject( JsonRoot, "State", RunStopStateWanted );
	
	// Print to text, Delete the cJSON, use it, release the string.
	TextReq = cJSON_Print( JsonRoot );
	cJSON_Delete( JsonRoot );
//to reuse it after now...	free( TextReq );
	return TextReq;
}

void MonitorParseResponseSetRunStopState( cJSON *JsonRoot, char SlaveMode )
{
	if ( !SlaveMode )
	{
		// get values from the response of the slave...
		// --------------------------------------------
		// nothing interesting to read back...
		InfosGUI->TargetMonitor.AskTargetToSetState = -1; //action request to target done
	}
	else
	{
		// get value wanted per the master
		int TargetStateWanted = cJSON_GetObjectItem( JsonRoot,"State" )->valueint;
printf("RECV ORDER RUN/STOP Target=%d - Wanted=%d\n",InfosGene->LadderState,TargetStateWanted);
		if ( ( InfosGene->LadderState==STATE_RUN && TargetStateWanted!=STATE_RUN )
			|| ( InfosGene->LadderState==STATE_STOP && TargetStateWanted!=STATE_STOP ) )
		{
printf("EXEC ORDER FLIP RUN/STOP\n");
			DoFlipFlopRunStop( );
		}
		// adds values responses for the response to the master !
		// ------------------------------------------------------
		// nothing usefull for the master...
	}
}

//for the master, to ask to reset the target
char * MonitorCreateRequestResetTarget( void )
{
	//create request...
	cJSON *JsonRoot;
	char * TextReq;
	
	JsonRoot = cJSON_CreateObject();
	
	cJSON_AddStringToObject( JsonRoot, "ReqCL", "ResetTarget" );
	
	// Print to text, Delete the cJSON, use it, release the string.
	TextReq = cJSON_Print( JsonRoot );
	cJSON_Delete( JsonRoot );
//to reuse it after now...	free( TextReq );
	return TextReq;
}

void MonitorParseResponseResetTarget( cJSON *JsonRoot, char SlaveMode )
{
	if ( !SlaveMode )
	{
		// get values from the response of the slave...
		// --------------------------------------------
		// nothing interesting to read back...
		InfosGUI->TargetMonitor.AskTargetToReset = -1; //action request to target done
	}
	else
	{
printf("RECV/EXEC ORDER Reset Target\n");
		DoReset( );
		// adds values responses for the response to the master !
		// ------------------------------------------------------
		// nothing usefull for the master...
	}
}

// The functions gettimeofday() and settimeofday() can get and set the time as well as a timezone. The tv argument is a struct timeval (as specified in <sys/time.h>):
//for the master, to ask to set its clock time with current PC one
char * MonitorCreateRequestSetClockTime( )
{
	//create request...
	cJSON *JsonRoot;
	char * TextReq = NULL;
//	struct timeval tv;
	char BuffCurrTime[ 30 ];
	GetCurrentAscTime( BuffCurrTime );
	
//	if ( gettimeofday( &tv, NULL )==0 )
//	{
		JsonRoot = cJSON_CreateObject();
	
		cJSON_AddStringToObject( JsonRoot, "ReqCL", "SetClockTime" );
	
		cJSON_AddStringToObject( JsonRoot, "AscTime", BuffCurrTime );
	
		// Print to text, Delete the cJSON, use it, release the string.
		TextReq = cJSON_Print( JsonRoot );
		cJSON_Delete( JsonRoot );
//to reuse it after now...	free( TextReq );
//	}
	return TextReq;
}

void MonitorParseResponseSetClockTime( cJSON *JsonRoot, char SlaveMode )
{
	if ( !SlaveMode )
	{
		// get values from the response of the slave...
		// --------------------------------------------
		// nothing interesting to read back...
		InfosGUI->TargetMonitor.AskTargetToSetClockTime = -1; //action request to target done
	}
	else
	{
		int Done = 0;
		// get value wanted per the master
		cJSON * CommandTimeVal = cJSON_GetObjectItem( JsonRoot,"AscTime" );
		if ( CommandTimeVal )
		{
			struct timeval tv;
			time_t TimeIntVal = ConvertAscToIntTime( CommandTimeVal->valuestring );
			tv.tv_sec = TimeIntVal;
			tv.tv_usec = 0;
printf("RECV/EXEC ORDER Set Clock Time=%d\n",(int)tv.tv_sec);
#ifndef __WIN32__
			if ( settimeofday( &tv, NULL )!=0 )
				printf("Failed to set clock time!!!");
			else
				Done = 1;
#endif
		}
		// adds values responses for the response to the master !
		// ------------------------------------------------------
		cJSON_AddNumberToObject( JsonRoot, "Done", Done );
	}
}

char * MonitorCreateRequestGetTargetInfosVersion( void )
{
	//create request...
	cJSON *JsonRoot;
	char * TextReq;
	
	JsonRoot = cJSON_CreateObject();
	
	cJSON_AddStringToObject( JsonRoot, "ReqCL", "GetTargetInfosVersion" );
	
	// Print to text, Delete the cJSON, use it, release the string.
	TextReq = cJSON_Print( JsonRoot );
	cJSON_Delete( JsonRoot );
//to reuse it after now...	free( TextReq );
	return TextReq;
}

void ReadKernelVersion( char * Buff )
{
	FILE * pFile;
	strcpy( Buff, "???" );
	pFile = fopen( "/proc/version", "rt" );
	if ( pFile )
	{
		fread( Buff, 1, 50, pFile );
		fclose( pFile );
		Buff[ 49 ] = '\0';
		// extract version number from string
		char * pStart = Buff;
		while( *pStart!='\0' && ( *pStart<'0' || *pStart>'9' || *pStart==' ' ) )
			pStart++;
		if ( *pStart!='\0' )
		{
			char * pEnd = pStart;
			while( *pEnd!=' ' && *pEnd!='\0' )
				pEnd++;
			if ( *pEnd!='\0' )
			{
				*pEnd = '\0';
				strcpy( Buff, pStart );
			}
		}
	}
}
void ReadDistribVersion( char * Buff )
{
	FILE * File;
	char Line[300];
	char * LineOk;
	strcpy( Buff, "???" );
	File = fopen( "/etc/lsb-release","rt");
	if (File)
	{
		do
		{
			LineOk = cl_fgets(Line,300,File);
			if (LineOk)
			{
				char * pParameter;
				pParameter = "DISTRIB_DESCRIPTION=";
				if ( strncmp( Line, pParameter, strlen( pParameter) )==0 )
				{
					if ( Line[ strlen( pParameter) ]=='\"' )
					{
						strcpy( Buff, &Line[ strlen( pParameter)+1 ] );
						Buff[ strlen( Buff )-1 ] = '\0';
					}
					else
					{
						strcpy( Buff, &Line[ strlen( pParameter) ] );
					}
				}
			}
		}
		while(LineOk);
		fclose(File);
	}
}

void MonitorParseResponseGetTargetInfosVersion( cJSON *JsonRoot, char SlaveMode )
{
	if ( !SlaveMode )
	{
		// get values from the response of the slave...
		// --------------------------------------------
		cJSON * JsonInfo;
		char * VersionSoft = cJSON_GetObjectItem( JsonRoot, "SoftVersion" )->valuestring;
printf("Version soft on target=%s\n",VersionSoft);
		strcpy( InfosGUI->TargetMonitor.InfoSoftVersion, VersionSoft );
		InfosGUI->TargetMonitor.InfoKernelVersion[ 0 ] = '\0';
		JsonInfo = cJSON_GetObjectItem( JsonRoot, "KernelVersion" );
		if ( JsonInfo )
			strcpy( InfosGUI->TargetMonitor.InfoKernelVersion, JsonInfo->valuestring );
		InfosGUI->TargetMonitor.InfoLinuxDistribVersion[ 0 ] = '\0';
		JsonInfo = cJSON_GetObjectItem( JsonRoot, "LinuxDistribVersion" );
		if ( JsonInfo )
			strcpy( InfosGUI->TargetMonitor.InfoLinuxDistribVersion, JsonInfo->valuestring );
		InfosGUI->TargetMonitor.AskTargetToGetTargetInfos = -1; //action request to target done
		InfosGUI->TargetMonitor.CmdDisplayTargetInfosVersion = TRUE;
	}
	else
	{
		// get value wanted per the master
		// --- nothing ---
		// adds values responses for the response to the master !
		// ------------------------------------------------------
		char Info[ 50 ];
		cJSON_AddStringToObject( JsonRoot, "SoftVersion", CL_RELEASE_VER_STRING " ("CL_RELEASE_DATE_STRING")" );
		ReadKernelVersion( Info );
		cJSON_AddStringToObject( JsonRoot, "KernelVersion", Info );
		ReadDistribVersion( Info );
		cJSON_AddStringToObject( JsonRoot, "LinuxDistribVersion", Info );
	}
}

char * MonitorCreateRequestGetProjectProperties( void )
{
	//create request...
	cJSON *JsonRoot;
	char * TextReq;
	
	JsonRoot = cJSON_CreateObject();
	
	cJSON_AddStringToObject( JsonRoot, "ReqCL", "GetProjectInfos" );
	
	// Print to text, Delete the cJSON, use it, release the string.
	TextReq = cJSON_Print( JsonRoot );
	cJSON_Delete( JsonRoot );
//to reuse it after now...	free( TextReq );
	return TextReq;
}

void MonitorParseResponseGetProjectProperties( cJSON *JsonRoot, char SlaveMode )
{
	if ( !SlaveMode )
	{
		// get values from the response of the slave...
		// --------------------------------------------
		char * ProjectName = cJSON_GetObjectItem( JsonRoot, "ProjectName" )->valuestring;
		char * ParamVersion = cJSON_GetObjectItem( JsonRoot, "ParamVersion" )->valuestring;
		char * ParamModifDate = cJSON_GetObjectItem( JsonRoot, "ParamModifDate" )->valuestring;
printf("Target project name=%s version=%s modifdate=%s\n",ProjectName,ParamVersion,ParamModifDate);
		if ( strcmp( InfosGene->ProjectProperties.ProjectName,ProjectName)!=0 || strcmp( InfosGene->ProjectProperties.ParamVersion,ParamVersion)!=0 
			|| strcmp( InfosGene->ProjectProperties.ParamModifDate,ParamModifDate)!=0 )
			strcpy( InfosGene->HardwareErrMsgToDisplay, "Mismatch detected between local parameters and target parameters...\nPerhaps you should disconnect!" );
		InfosGUI->TargetMonitor.AskTargetToGetProjectProperties = -1; //action request to target done
		InfosGUI->TargetMonitor.CmdDisplayTargetInfosVersion = TRUE;
	}
	else
	{
		// get value wanted per the master
		// --- nothing ---
		// adds values responses for the response to the master !
		// ------------------------------------------------------
		cJSON_AddStringToObject( JsonRoot, "ProjectName", InfosGene->ProjectProperties.ProjectName );
		cJSON_AddStringToObject( JsonRoot, "ParamVersion", InfosGene->ProjectProperties.ParamVersion );
		cJSON_AddStringToObject( JsonRoot, "ParamAuthor", InfosGene->ProjectProperties.ParamAuthor );
		cJSON_AddStringToObject( JsonRoot, "ParamCreaDate", InfosGene->ProjectProperties.ParamCreaDate );
		cJSON_AddStringToObject( JsonRoot, "ParamModifDate", InfosGene->ProjectProperties.ParamModifDate );
	}
}

//for the master, to ask to reset the target
char * MonitorCreateRequestRebootTarget( void )
{
	//create request...
	cJSON *JsonRoot;
	char * TextReq;
	
	JsonRoot = cJSON_CreateObject();
	
	cJSON_AddStringToObject( JsonRoot, "ReqCL", "RebootTarget" );
	
	// Print to text, Delete the cJSON, use it, release the string.
	TextReq = cJSON_Print( JsonRoot );
	cJSON_Delete( JsonRoot );
//to reuse it after now...	free( TextReq );
	return TextReq;
}

void MonitorParseResponseRebootTarget( cJSON *JsonRoot, char SlaveMode )
{
	if ( !SlaveMode )
	{
		// get values from the response of the slave...
		// --------------------------------------------
		// nothing interesting to read back...
		InfosGUI->TargetMonitor.AskTargetToReboot = -1; //action request to target done
	}
	else
	{
printf("RECV/EXEC ORDER Reboot the system\n");
#ifndef GTK_INTERFACE
kill(1/*initpid*/, SIGTERM);
#endif
		// adds values responses for the response to the master !
		// ------------------------------------------------------
		// nothing usefull for the master...
	}
}
